/**
 * @author 迷途小羔羊
 * 2014-11-19
 */
namespace GYLite
{
	/**MyLoader是一个loader和urlloader封装的多任务加载器*/
	export class GYLoader
	{
		private static _loader:GYLoader;
		public static getDefaultLoader():GYLoader
		{
			if(GYLoader._loader == null)
				GYLoader._loader = new GYLoader(30,30);
			return GYLoader._loader;
		}
		
		/**支持的解析类型1 blob 2 base64*/public static supportBlobMP3:number = 1;
		/**支持的解析类型1 blob 2 base64*/public static supportBlobWAV:number = 1;
		/**自定义压缩的音频解析类*/public static defCompressSound:any;		

		public static imageToGPU:boolean;		
		private static _resDict:{[key:string]:ResObject}={};
		private static _resDataDict:{[key:string]:ResObject}={};
		private _seqLoaderList:Array<SeqLoader>;
		private _seqURLLoaderList:Array<SeqURLLoader>;
		private _loadList:Array<LoadInfo>;
		private _urlLoadList:Array<LoadInfo>;
		private _loaderReq = new URLRequest();
		private _httpReq = new URLRequest();			
		private static _checkTime:number;
		private static _checkInterval:number;
		private static _timeId:number;
		public static miniGame:any;
		/**
		 * @param loaderThreads Loader的线程数量 默认为1
		 * @param urlLoaderThreads UrlLoader的线程数量 默认为0
		 * @param 微信加载器，若存在则使用微信加载器方式加载
		 * */
		public constructor(loaderThreads=1,urlLoaderThreads=0)
		{
			let s = this;			
			if(loaderThreads > 0)
			{
				s._seqLoaderList=new Array(loaderThreads);//(loaderThreads,true);
				s._loadList=[];//new Array<LoadInfo>;
			}

			if(urlLoaderThreads > 0)
			{
				s._seqURLLoaderList=new Array(urlLoaderThreads);//(urlLoaderThreads,true);
				s._urlLoadList=[];//new Array<LoadInfo>;
			}			
		}
		private getLoader(loadInfo:LoadInfo):SeqLoader
		{
			var len:number;
			var l:SeqLoader,waitL:SeqLoader;
			let s = this;
			len=s._seqLoaderList.length;
			while(--len > -1)
			{
				l=s._seqLoaderList[len];
				if(l)
				{
					if(l.loadInfo)
					{
						if(l.loadInfo.path == loadInfo.path && l.loadInfo.bytes == loadInfo.bytes)
						{
							if(waitL)
								waitL.loadInfo=null;
							waitL=l;
							if(l.isLoading == 2)
							{
								loadInfo.content = l.loadInfo.content;
								loadInfo.callBack();
							}
							else
								l.loadInfo.addLoadInfo(loadInfo);
							break;
						}
					}
					else if(waitL==null)
					{
						waitL=l;
						waitL.loadInfo = loadInfo;
					}
				}
				else
				{
					if(waitL == null)
					{
						s._seqLoaderList[len]=waitL=new SeqLoader;
						waitL.addEventListener(egret.Event.COMPLETE,s.LoadComp,s);
						waitL.addEventListener(egret.IOErrorEvent.IO_ERROR,s.LoadError,s);
						//waitL.addEventListener(ProgressEvent.PROGRESS,ProgFunc);
						waitL.loadInfo = loadInfo
					}
					break;
				}
			}
			return waitL;
		}
		private getURLLoader(loadInfo:LoadInfo):SeqURLLoader
		{
			var len:number;
			var l:SeqURLLoader,waitL:SeqURLLoader;
			let s = this;
			len=s._seqURLLoaderList.length;
			while(--len > -1)
			{
				l=s._seqURLLoaderList[len];
				if(l)
				{
					if(l.loadInfo)
					{
						if(l.loadInfo.path == loadInfo.path && loadInfo.sendType != LoadInfo.SEND_HTTP)
						{
							if(waitL)
								waitL.loadInfo=null;
							waitL=l;
							if(l.isLoading == 2)
							{
								loadInfo.content = l.loadInfo.content;
								loadInfo.callBack();
							}
							else
								l.loadInfo.addLoadInfo(loadInfo);
							break;
						}
					}
					else if(waitL==null)
					{
						waitL=l;
						waitL.loadInfo = loadInfo;
					}
				}
				else
				{
					if(waitL == null)
					{
						s._seqURLLoaderList[len]=waitL=new SeqURLLoader;
						waitL.addEventListener(egret.Event.COMPLETE, s.UrlLoadComp,s);
						waitL.addEventListener(egret.IOErrorEvent.IO_ERROR, s.URLLoadError,s);
						// waitL.addEventListener(SecurityErrorEvent.SECURITY_ERROR, s.SecurityErr,s);
						waitL.addEventListener("progress", s.UrlProgFunc,s);
						waitL.loadInfo = loadInfo
					}
					break;
				}
			}
			return waitL;
		}

		/**读取bytes资源 png jpg bmp
		 * @param bytes uint8Array或者ByteArray的buffer属性
		 * @param callBackFunc 回调函数，返回参数为LoadInfo,返回后，loadInfo会自动被清理
		 * @param thisObject callBackFunc的this指向
		 * @param type 加载资源html blob类型 image(如image/png)，默认1
		 * @param mimeType blob资源 如"image/png" 图片文件 "audio/basic" 声音文件，默认"image/png"
		 * @param param 附加参数，默认null
		 * @param retainBytes 是否保留加载的文件字节数据，默认false
		 * @param lifeTime 资源存活周期，默认NaN，永久存活
		 * */
		public loadBytes(bytes:ArrayBuffer, callBackFunc:Function, thisObject:any, type:number = 1,mimeType="image/png",param:any = null,retainBytes:boolean=false,lifeTime:number=NaN):LoadInfo
		{
			if(GYLoader._disposed)return;
			let s = this;
			var loadInfo=LoadInfo.create();
			loadInfo.thisObject = thisObject;
			loadInfo.bytes=bytes;
			loadInfo.callBackFunc=callBackFunc;
			// loadInfo.progFunc=progFunc;
			loadInfo.type = type;
			loadInfo.mimeType = mimeType;
			loadInfo.sendType = LoadInfo.SEND_DATA;
			loadInfo.param = param;
			loadInfo.retainBytes = retainBytes;
			loadInfo.startTime = Date.now();
			let key:string = GYByteArray.getBytesHash(bytes);
			if(GYLoader._resDict[key])
			{
				loadInfo.content=GYLoader._resDict[key];
				loadInfo.msg="加载完成！";
				callBackFunc(loadInfo);
				loadInfo.clear();
				return loadInfo;
			}
			var len:number;
			len=s._loadList.length;
			while(--len>-1)
			{
				if(key == GYByteArray.getBytesHash(s._loadList[len].bytes))
				{
					s._loadList[len].addLoadInfo(loadInfo);
					return loadInfo;
				}
			}
			var l=s.getLoader(loadInfo);
			if(l)
			{
				if(l.isLoading == 0)
				{
					l.isLoading = 1;
					l.loadBytes(bytes);					
				}
			}
			else
				s._loadList.push(loadInfo);
			return loadInfo;
		}
		/**读取GYPackager打包的资源
		 * @param bytes uint8Array或者ByteArray的buffer属性
		 * @param callBackFunc 回调函数，返回参数为CompressLoadInfo
		 * @param callBackFunc指向
		 * @param version 资源版本号
		 * @param progFunc 回调函数，返回参数为CompressLoadInfo
		 * @param param 附加参数 在CompressLoadInfo.param处返回
		 * @param retainBytes 是否保留加载的文件字节数据
		 * */
		public loadGYCompressBytes(buffer:ArrayBuffer,callBackFunc:Function,thisObject:any,version:string = null,progFunc:Function=null,param:any=null,retainBytes:boolean=false):CompressLoadInfo
		{let s = this;
			if(GYLoader._disposed)return;
			let v:string;
			let i:number,len:number,size:number;
			let path:string,cp;
			let type;
			let newBytes:GYByteArray,bytes:GYByteArray;
			let bLen:number,pos:number;
			let cpLoadInfo:CompressLoadInfo;
			let res:GYLite.ResObject;
			let correct:boolean = false;
			let v1:number,v2:number,v3:number;			 
			let vArr:string[];
			bytes = new GYByteArray(buffer);			
			if(bytes.readUTF() == "GYCompress")
			{
				cpLoadInfo = new CompressLoadInfo;
				cpLoadInfo.param = param;
				cpLoadInfo.callBackFunc = callBackFunc;
				cpLoadInfo.progFunc = progFunc;
				cpLoadInfo.thisObject = thisObject;				
				version = version == null?"":"?"+version;
				v = bytes.readUTF();
				vArr = v.split(".");
				v1 = Number(vArr[0].substr(1));
				v2 = Number(vArr[1]);
				v3 = Number(vArr[1]);
				if(v1 > 1)
				{
					pos = bytes.position;
					if(bytes.length > 4)
					{
						bytes.position = bytes.length - 4;
						size=len = bytes.readUnsignedInt();
						correct = len == bytes.length - 4;
					}
					if(!correct)
					{		
						cpLoadInfo.msg = "#1文件损坏" + len + "-" + (bytes.length - 4);
						cpLoadInfo.errorCode = 1;
						cpLoadInfo.setResCount(1,1);
						cpLoadInfo.callBack();
						return;
					}
					bytes.position = pos;
				}
				
				cpLoadInfo.errorCode = 0;
				
				len = bytes.readUnsignedInt();
				cpLoadInfo.setResCount(len,len);
				cpLoadInfo.progressInfo.push({length:len,version:v,size:size});
				if(len > 0)
				{
					for(i=0;i<len;++i)
					{
						path = bytes.readUTF() + version;
						type = bytes.readUnsignedInt();
						cp = bytes.readUTF();
						bLen = bytes.readUnsignedInt();
						newBytes = new GYByteArray;
						bytes.readBytes(newBytes,0,bLen);
						if(cp!="none")
							newBytes.uncompress(cp);
						if(type == LoadType.TYPE_SOUND && GYLoader.defCompressSound)
						{
							res = ResObject.create();
							res.type = type;
							res.res = new GYLoader.defCompressSound;
							let iSound:ISound = (<ISound>res.res);
							iSound.bytes = newBytes.buffer;
							iSound.mimeType = GYLoader.getMimeType(type, path);
							iSound.compress = cp;
							iSound.path = path;							
							res.pathKey = path;
							if(retainBytes)
							{					
								newBytes.position = 0;		
								res.param.bytes = newBytes;
							}											
							GYLoader.setRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}
						else if(type == LoadType.TYPE_SPINE || type == LoadType.TYPE_ATLAS || type == LoadType.TYPE_IMAGE || type == LoadType.TYPE_TEX || type == LoadType.TYPE_SOUND)
						{							
							cpLoadInfo.loadBytes(newBytes.buffer,type,GYLoader.getMimeType(type, path),{compress:cp,url:path},path,retainBytes);
						}
						else if(type == LoadType.TYPE_FONT)
						{
							res = ResObject.create();
							res.type = type;							
							res.pathKey = path;
							const blob = new Blob([newBytes.buffer], { type: 'application/octet-stream' });
							let arr:string[] = path.split(/\/|\\/g);
							let name:string;
							name = arr[arr.length - 1].split(".")[0];
							res.res = ResParser.createFontStyle(name,blob);
							GYLoader.setDataRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}
						else if(type == LoadType.TYPE_JSON)
						{
							res = ResObject.create();
							res.type = type;
							res.res = JSON.parse(newBytes.readUTFBytes(newBytes.length));
							res.pathKey = path;
							if(retainBytes)
							{					
								newBytes.position = 0;		
								res.param.bytes = newBytes;
							}
							GYLoader.setDataRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}
						else if(type == LoadType.TYPE_TEXT || type == LoadType.TYPE_JS)
						{
							res = ResObject.create();
							res.type = type;
							res.res = newBytes.readUTFBytes(newBytes.length);
							res.pathKey = path;
							if(retainBytes)
							{					
								newBytes.position = 0;		
								res.param.bytes = newBytes;
							}
							GYLoader.setDataRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}											
						else if(type == LoadType.TYPE_URL_RES)
						{
							//short-type,utf-url
							let url:string;
							let resType:number;							
							resType = newBytes.readShort();
							url = newBytes.readUTF();//url
							if(resType == LoadType.TYPE_SPINE || resType == LoadType.TYPE_ATLAS || resType == LoadType.TYPE_IMAGE || resType == LoadType.TYPE_TEX || resType == LoadType.TYPE_SOUND)
								cpLoadInfo.loadPath(url,resType);
							else
								cpLoadInfo.loadData(url,resType);
						}
						else
						{
							res = ResObject.create();
							res.type = type;
							res.res = newBytes.buffer;
							res.pathKey = path;
							if(retainBytes)
							{					
								newBytes.position = 0;		
								res.param.bytes = newBytes;
							}
							GYLoader.setDataRes(path,res);
							cpLoadInfo.callBack(null,path,Date.now());
						}						
					}
				}
				else
				{
					cpLoadInfo.setResCount(1,1);
					cpLoadInfo.callBack();
				}				
			}
			return cpLoadInfo;
		}
		/**加载，自动区分是图片或声音、数据文件、图集，参数参考loadPath和loadData
		 * @param path 资源url
		 * @param callBackFunc 回调函数，返回参数为LoadInfo,返回后，loadInfo会自动被清理
		 * @param thisObject callBackFunc的this指向
		 * @param type 资源类型 默认LoadType.TYPE_IMAGE
		 * @param method request方法 默认"get"
		 * @param param 附加参数 默认null
		 * @param progFunc 进度回调 默认null
		 * @param lifeTime 资源存活周期，默认NaN，永久存活
		*/
		public load(path:string,callBackFunc:Function,thisObject:any, type:LoadType=LoadType.TYPE_IMAGE, method:string="get", param:InfoParam = null, progFunc:Function=null,lifeTime:number=NaN):LoadInfo
		{
			if(type == LoadType.TYPE_SPINE)//加载spine把json、atlas也一块加载了
				return this.loadAssets([path.replace(".png", ".json"), LoadType.TYPE_JSON, path.replace(".png", ".atlas"), LoadType.TYPE_TEXT, path, LoadType.TYPE_SPINE], callBackFunc, thisObject, param, lifeTime);
			if(type == LoadType.TYPE_ATLAS)//加载图集把json也一块加载了
				return this.loadAssets([path.replace(".png", ".json"), LoadType.TYPE_JSON, path, LoadType.TYPE_ATLAS], callBackFunc, thisObject, param, lifeTime);
			if(type == LoadType.TYPE_IMAGE || type == LoadType.TYPE_TEX || type == LoadType.TYPE_SOUND)
				return this.loadPath(path, callBackFunc,thisObject, type,param, lifeTime);
			return this.loadData(path, callBackFunc, thisObject, progFunc, type, method, param, lifeTime);
		}
		/**加载资源集合，请对最后加载回调返回的ResObject进行资源引用，以保持对整组资源的引用
		 * @param assets 资源集合 [路径，加载类型，路径，加载类型]，例如图集 [a.png,LoadType.ATLAS,a.json,LoadType.ATLAS]，注意把最重要的主资源放在第一个（因为是按列表顺序加载的）
		 * @param callBackFunc 回调函数，返回参数为LoadInfo,返回后，loadInfo会自动被清理
		 * @param thisObject callBackFunc的this指向
		 * @param param 附加参数，默认null
		 * @param lifeTime 资源存活周期，默认NaN，永久存活
		*/
		public loadAssets(assets:any[], callBackFunc:Function, thisObject:any, param:InfoParam = null,lifeTime:number=NaN):LoadInfo
		{
			let s= this;			
			param = {callBackFunc:callBackFunc, thisObject:thisObject, param:param, assets:assets, lifeTime:lifeTime};
			return s.nextAsset(assets, param);
		}
		private assetsLoadComp(loadInfo:LoadInfo):void
		{
			let s= this;	
			let func:Function,obj:any;			
			if(loadInfo.hasRes())
			{//加载成功
				if(loadInfo.param.assets.length > 0)//下一个
				{
					if(loadInfo.param.refResObjects == null)loadInfo.param.refResObjects = [];
					loadInfo.param.refResObjects[loadInfo.param.refResObjects.length] = loadInfo.content;
					s.nextAsset(loadInfo.param.assets, loadInfo.param);
					return;
				}
				//最后一个资源都加载完了
				loadInfo.content.setRefResObject(loadInfo.param.refResObjects);
				loadInfo.content.lifeTime = loadInfo.param.lifeTime;
			}
			else
			{//加载失败,把之前加载的资源都销毁
				let len:number;
				if(loadInfo.param.refResObjects)
				{
					len = loadInfo.param.refResObjects.length;
					while(--len > -1)
						loadInfo.param.refResObjects[len].dispose();					
					loadInfo.param.refResObjects.length = 0;
				}
			}

			func = loadInfo.param.callBackFunc;
			obj = loadInfo.param.thisObject;
			loadInfo.param = loadInfo.param.param;
			func.call(obj, loadInfo);
		}
		private nextAsset(assets:any[], param:InfoParam):LoadInfo
		{
			let s= this;
			let type:number;
			let path:string;
			type = assets.pop();
			path = assets.pop();
			if(type == LoadType.TYPE_SPINE || type == LoadType.TYPE_ATLAS || type == LoadType.TYPE_IMAGE || type == LoadType.TYPE_TEX || type == LoadType.TYPE_SOUND)
				return s.loadPath(path, s.assetsLoadComp, s, type, param);
			else
				return s.loadData(path, s.assetsLoadComp, s, null, type, "get", param);
		}		

		/**读取网络资源 swf png jpg bmp
		 * @param path 读取路径
		 * @param callBackFunc 回调函数，返回参数为LoadInfo,返回后，loadInfo会自动被清理
		 * @param thisObject callBackFunc的this指向
		 * @param type 加载资源类型 image(png,jpg), swf, font
		 * @param param 附加参数，默认null
		 * @param lifeTime 资源存活周期，默认NaN，永久存活
		 * */
		public loadPath(path:string,callBackFunc:Function, thisObject:any, type:LoadType=LoadType.TYPE_IMAGE, param:any = null, lifeTime:number=NaN):LoadInfo
		{
			if(GYLoader._disposed)return;
			let s = this;
			var loadInfo=LoadInfo.create();
			let loadUrl:string = path;
			let arr:string[];
			arr = path.split("?");
			path = arr[0];//分离路径和版本参数
			loadInfo.version = arr[1];
			loadInfo.lifeTime = lifeTime;
			loadInfo.thisObject = thisObject;
			loadInfo.path=path;
			loadInfo.callBackFunc=callBackFunc;
			loadInfo.param = param;
			// loadInfo.progFunc=progFunc;
			loadInfo.type = type;
			loadInfo.sendType = LoadInfo.SEND_RES;
			loadInfo.startTime = Date.now();
			if(GYLoader._resDict[path])
			{
				loadInfo.content=GYLoader._resDict[path];
				loadInfo.msg="加载完成！";
				callBackFunc.call(loadInfo.thisObject, loadInfo);
				loadInfo.clear();
				return null;
			}
			var len;
			len=s._loadList.length;
			while(--len>-1)
			{
				if(path == s._loadList[len].path)
				{
					s._loadList[len].addLoadInfo(loadInfo);
					return loadInfo;
				}
			}
			var l=s.getLoader(loadInfo);
			if(l)
			{
				if(l.isLoading == 0)
				{
					l.isLoading = 1;					
					l.load(loadUrl);					
				}
			}
			else
				s._loadList.push(loadInfo);
			return loadInfo;
		}
		/**取消加载，当调用loadPath加载资源时，调用此方法取消加载，此方法根据path和callBackFunc寻找此前的加载请求
		 * @param path	加载路径
		 * @param callBackFunc 加载完成的回调
		 * */
		public cancelLoadPath(path:string, callBackFunc:Function, thisObject:any):boolean
		{
			var len:number;
			var l:SeqLoader;
			var loadInfo:LoadInfo;
			let s = this;
			len=s._seqLoaderList.length;
			while(--len > -1)
			{
				l = s._seqLoaderList[len];
				if(l && l.loadInfo && l.loadInfo.includeAssets(path))
				{
					if(l.loadInfo.cancel(callBackFunc, thisObject))
					{
						l.cancelLockTime = Date.now();
						l.callLater(function(seqLoader){
							let sThis = this;
							seqLoader.breakLock();
							sThis.LoadNext(l);
						},s,0);
						l.loadInfo = null;
						s.LoadNext(l);						
					}
					return true;
				}
			}
			len = s._loadList.length;
			while(--len>-1)
			{
				loadInfo = s._loadList[len];
				if(loadInfo.path == path)
				{
					if(loadInfo.cancel(callBackFunc, loadInfo.thisObject))
						s._loadList.splice(len,1);
					return true;
				}				
			}
			return false;
		}		
		private LoadError(e)
		{
			if(GYLoader._disposed)return;
			let s = this;
			var l = e.currentTarget;
			var loadInfo=l.loadInfo;
			if(loadInfo == null)return;
			loadInfo.msg="数据流错误#1";
			l.callLater(s.ErrorNext, s);
		}
		private ErrorNext(l:SeqLoader)
		{
			let s = this;
			l.clearCallLater();
			if(l.loadInfo == null)return;
			l.loadInfo.callBack();
			l.loadInfo.clear();
			l.loadInfo=null;
			s.LoadNext(l);
		}
		private LoadComp(e):void
		{
			if(GYLoader._disposed)return;
			let s = this;
			let l:SeqLoader;
			let loadInfo:LoadInfo;
			let type:number;
			let resObj:ResObject;
			l = e.currentTarget;
			loadInfo=l.loadInfo;
			if(loadInfo == null)return;
			l.isLoading = 2;
			type = loadInfo.type;
			resObj = ResParser.resParse(l);
			if(loadInfo.save)
			{
				if (loadInfo.path == null && loadInfo.type == LoadType.TYPE_SOUND)
					GYLoader.setRes(e.currentTarget.data.url, resObj);                    
                else
					GYLoader.setRes(loadInfo.path, resObj);					
				if(loadInfo.retainBytes)
					resObj.param.bytes = new GYByteArray(loadInfo.bytes);
			}
			loadInfo.content = resObj;
			loadInfo.msg="加载完成";
			loadInfo.callBack();
			loadInfo.clear();
			l.loadInfo=null;
			s.LoadNext(l);
		}		
		private LoadNext(l:SeqLoader)
		{
			if(GYLoader._disposed)return;
			let s = this;
			if(s._loadList.length > 0)
			{
				var loadInfo=s._loadList.shift();
				l.loadInfo = loadInfo;
				if(l.isLoading!=1)
				{
					l.isLoading = 1;
					if(loadInfo.bytes)
						l.loadBytes(loadInfo.bytes);
					else						
						l.load(loadInfo.path);										
				}
				return;
			}
		}
		/**httpSend请求
		 * @param url 请求的url
		 * @param callBackFunc 回调函数，返回参数为LoadInfo
		 * @param thisObject callBackFunc的this指向     *
		 * @param type  二进制(binary)、文本(text)、URL 编码变量(variables) 参考GYLoader常量
		 * @param method 访问方式 get 或者 post
		 * @param header 头部数据(Array[{key,value}])
		 * @param data 发送数据
		 * @param param 回调附加参数object
		 * */
		public httpSend(url:string,callBackFunc:Function, thisObject:any, type:LoadType=LoadType.TYPE_TEXT, method:string="get", header:Array<any> = null, data:any = null,contentType:string="",param:any = null)
		{
			if(GYLoader._disposed)return;
			let s = this;
			var loadInfo=LoadInfo.create();

			loadInfo.path=url;
			loadInfo.callBackFunc=callBackFunc;			
			loadInfo.thisObject = thisObject;
			loadInfo.type = type;
			loadInfo.method = method;
			loadInfo.param = param;
			loadInfo.contentType = contentType;
			loadInfo.header = header;
			loadInfo.save = false;
			loadInfo.data = data;
			loadInfo.sendType = LoadInfo.SEND_HTTP;
			loadInfo.startTime = Date.now();
			var len;
			len=s._urlLoadList.length;
			while(--len>-1)
			{
				if(url == s._urlLoadList[len].path)
				{
					s._urlLoadList[len].addLoadInfo(loadInfo);
					return loadInfo;
				}
			}
			var l=s.getURLLoader(loadInfo);
			if(l)
			{
				if(l.isLoading == 0)
				{
					l.isLoading = 1;
					s._httpReq.url = loadInfo.path;
					s._httpReq.method = loadInfo.method;
					s._httpReq.dataFormat = loadInfo.dataFormat;
					s._httpReq.data = loadInfo.data;
                	s._httpReq.requestHeaders = loadInfo.header;
					s._httpReq.contentType = contentType;
					l.load(s._httpReq);					
				}
			}
			else
				s._urlLoadList.push(loadInfo);
			return loadInfo;
		}
		/**加载数据
		 * @param path 读取路径
		 * @param callBackFunc 回调函数，返回参数为LoadInfo
		 * @param thisObject callBackFunc的this指向
		 * @param progFunc 回调函数，返回参数为ProgressEvent
		 * @param type  二进制(binary)、文本(text)、URL 编码变量(variables)
		 * @param method 访问方式 get 或者 post
		 * @param param 附加参数，默认null
		 * @param lifeTime 资源存活周期，默认NaN，永久存活
		 * */
		public loadData(path:string, callBackFunc:Function, thisObject:any, progFunc:any=null, type:LoadType=LoadType.TYPE_TEXT, method:string = "get", param:any = null, lifeTime:number=NaN):LoadInfo
		{
			if(GYLoader._disposed)return;
			let s = this;
			var loadInfo=LoadInfo.create();
			let loadUrl:string = path;
			let arr:string[];
			arr = path.split("?");
			path = arr[0];//分离路径和版本参数
			loadInfo.version = arr[1];
			loadInfo.lifeTime = lifeTime;
			loadInfo.path=path;
			loadInfo.callBackFunc=callBackFunc;
			loadInfo.progFunc=progFunc;
			loadInfo.thisObject = thisObject;
			loadInfo.type = type;
			loadInfo.method = method;
			loadInfo.param = param;
			loadInfo.sendType = LoadInfo.SEND_DATA;
			loadInfo.startTime = Date.now();
			if(GYLoader._resDataDict[path])
			{
				loadInfo.content=GYLoader._resDataDict[path];
				loadInfo.msg="加载完成！";
				callBackFunc.call(loadInfo.thisObject,loadInfo);
				loadInfo.clear();
				return null;
			}
			var len;
			len=s._urlLoadList.length;
			while(--len>-1)
			{
				if(path == s._urlLoadList[len].path)
				{
					s._urlLoadList[len].addLoadInfo(loadInfo);
					return loadInfo;
				}
			}
			var l=s.getURLLoader(loadInfo);
			if(l)
			{
				if(l.isLoading == 0)
				{
					l.isLoading = 1;
					s._loaderReq.url=loadUrl;
					s._loaderReq.method=method;
					s._loaderReq.dataFormat = loadInfo.dataFormat;
					l.load(s._loaderReq);					
				}
			}
			else
				s._urlLoadList.push(loadInfo);
			return loadInfo;
		}
		/**取消加载，当调用loadPath加载数据时，调用此方法取消加载，此方法根据path和callBackFunc寻找此前的加载请求
		 * @param path	加载路径
		 * @param callBackFunc 加载完成的回调
		 * */
		public cancelLoadData(path:string, callBackFunc:Function, thisObject:any):boolean
		{
			let s = this;
			var len:number;
			var l:SeqURLLoader;
			var loadInfo:LoadInfo;
			len=s._seqURLLoaderList.length;
			while(--len > -1)
			{
				l = s._seqURLLoaderList[len];
				if(l && l.loadInfo && l.loadInfo.includeAssets(path))
				{
					if(l.loadInfo.cancel(callBackFunc,thisObject))
					{
						l.cancelLockTime = Date.now();
						l.callLater(function(l){
							let sThis = this;
							l.breakLock();
							sThis.UrlLoadNext(l)
						},s,0);
						l.loadInfo = null;
						l.close();
					}
					return true;
				}
			}
			len = s._urlLoadList.length;
			while(--len>-1)
			{
				loadInfo = s._urlLoadList[len];
				if(loadInfo.path == path)
				{
					if(loadInfo.cancel(callBackFunc,loadInfo.thisObject))
						s._urlLoadList.splice(len,1);
					return true;
				}
			}
			return false;
		}
		private UrlLoadComp(e):void
		{
			if(GYLoader._disposed)return;
			let s = this;
			var l:SeqURLLoader = e.currentTarget;
			var loadInfo:GYLite.LoadInfo;
			var resObj:GYLite.ResObject;			

			loadInfo =l.loadInfo;
			if(loadInfo == null)//已经终止
				return;			
			if(l.data == null || loadInfo.status >= 300 && loadInfo.status != 0)
			{
				loadInfo.msg="数据为异常！status:" + loadInfo.status + "#3";
				loadInfo.callBack();
				l.callLater(s.UrlErrorNext,s);
				return;
			}
			
			l.isLoading = 2;
			resObj = ResParser.bytesParse(l);
			if(loadInfo.save)
			{
				GYLoader.setDataRes(loadInfo.path, resObj);				
				if(loadInfo.retainBytes)
					resObj.param.bytes = new GYByteArray(loadInfo.bytes);
			}
			loadInfo.content = resObj;
			loadInfo.msg="加载完成！";
			loadInfo.callBack();
			loadInfo.clear();
			l.loadInfo = null;
			s.UrlLoadNext(l);
		}		
		private URLLoadError(e)
		{
			if(GYLoader._disposed)return;
			let s = this;
			var l:SeqURLLoader = e.currentTarget;
			var loadInfo=l.loadInfo;
			if(loadInfo == null)return;
			loadInfo.msg="数据流错误！#1";
			loadInfo.callBack();
			l.callLater(s.UrlErrorNext,s);
		}
		// private SecurityErr(e:SecurityErrorEvent):void
		// {
		// 	let s = this;
		// 	var l:SeqURLLoader = e.currentTarget as SeqURLLoader;
		// 	var loadInfo:LoadInfo=l.loadInfo;
		// 	loadInfo.msg="沙箱错误！#2";
		// 	loadInfo.callBack();
		// 	loadInfo.clear();
		// 	l.callLater(UrlErrorNext);
		// }
		private UrlErrorNext(l)
		{			
			let s = this;
			l.clearCallLater();
			if(l.loadInfo == null)return;
			l.loadInfo=null;
			s.UrlLoadNext(l);
		}
		private UrlProgFunc(e)
		{
			if(GYLoader._disposed)return;
			var loadInfo = e.currentTarget.loadInfo
			loadInfo.prog(e);
		}
		private UrlLoadNext(l)
		{
			if(GYLoader._disposed)return;
			let s = this;
			if(s._urlLoadList.length > 0)
			{
				var loadInfo=s._urlLoadList.shift();
				l.loadInfo = loadInfo;
				if(l.isLoading!=1)
				{
					l.isLoading = 1;
					if(loadInfo.sendType == LoadInfo.SEND_HTTP)
					{
						s._httpReq.dataFormat = loadInfo.dataFormat;
						s._httpReq.url = loadInfo.path;
						s._httpReq.method = loadInfo.method;
						s._httpReq.contentType = loadInfo.contentType;
						s._httpReq.requestHeaders = loadInfo.header;
						s._httpReq.data = loadInfo.data;
						l.load(s._httpReq);
					}
					else
					{
						s._loaderReq.dataFormat = loadInfo.dataFormat;
						s._loaderReq.url = loadInfo.path;
						s._loaderReq.method = loadInfo.method;
						s._loaderReq.contentType = loadInfo.contentType;						
						l.load(s._loaderReq);
					}
					return;
				}
			}
		}
		public static getMimeType(type:number, path:string = null):string
		{			
			let arr:Array<string>;
			let ext:string;			
			if(path)
			{
				arr = path.split(".");
				ext = arr.length > 1?arr[arr.length - 1]:null;
				arr = ext.split("?");
				if(arr.length > 1)				
					ext = arr[0];				
				arr = ext.split("$");
				if(arr.length > 1)				
					ext = arr[0];				
			}
				
			if(type == LoadType.TYPE_SOUND)
			{				
				if(ext)
					return "audio/" + ext;
				return "audio/basic";
			}
			if(type == LoadType.TYPE_FONT)
			{				
				if(ext)
					return "font/" + ext;
				return "font/ttf";
			}
			if(ext == "jpg")
			{
				return "image/jpeg";
			}
			if(ext)
				return "image/" + ext;
			return "image/png";
		}
		public static getImageMemory():number
		{
			let total:number = 0;
			let dict:any = GYLoader._resDict;
			let resObj:ResObject;
			for(let key in dict)
			{
				resObj = dict[key];
				if(resObj.type == LoadType.TYPE_IMAGE && resObj.pathKey.indexOf("$") == -1 || resObj.type == LoadType.TYPE_TEX)
				{
					let img:HTMLImageElement = resObj.res.bitmapData.source;
					if(img)
						total += img.width * img.height * 4;
				}
			}
			return total;
		}
		public static getImageGPUMemory():number
		{
			let total:number = 0;
			let dict:any = GYLoader._resDict;
			let resObj:ResObject;
			for(let key in dict)
			{
				resObj = dict[key];
				if(resObj.type == LoadType.TYPE_IMAGE && resObj.pathKey.indexOf("$") == -1 || resObj.type == LoadType.TYPE_TEX)
				{
					total += resObj.res.textureWidth * resObj.res.textureWidth * 4;
				}
			}
			return total;
		}		
		/**检测销毁对象的引用资源回收的时间间隔(毫秒)，小于等于0时不回收*/
		public static setResCheck(val:number):void
		{			
			if(GYLoader._checkInterval > 0)
			{
				TimeManager.unRegistered(GYLoader._timeId,GYLoader.checkResUse, null);
			}
			GYLoader._checkInterval = val;
			if(val > 0)
			{
				GYLoader._checkTime = Date.now();
				GYLoader._timeId = TimeManager.registered(GYLoader.checkResUse, null);
			}
		}
		/**检测销毁对象的引用，忽略存活周期等待，对引用为0的对象进行回收(此方法耗费性能)**/
		public static checkResUse(sysTime:number):void
		{			
			if(sysTime - GYLoader._checkTime < GYLoader._checkInterval)
				return;
			if(GYLoader._disposed)
			{
				GYLoader.setResCheck(-1);
				return;
			}
			GYLoader._checkTime = sysTime;			
			for (var key in GYLoader._resDict)
			{
				if(!GYLoader._resDict[key].inUse())				
					GYLoader._resDict[key].dispose();
			}
			
			for (var key in GYLoader._resDataDict)
			{
				if(!GYLoader._resDict[key].inUse())				
					GYLoader._resDict[key].dispose();
			}			
		}
		/**获取包含key键的数据资源,假设data文件夹下面的资源，如 data/,结尾带上/，以便区分文件夹节点 
		 * @param searchKey 资源键名
		 * @param exact 是否完全匹配 默认false
		 * @param ignoreVersion 匹配忽略版本号
		*/
		public static getDataResByKey(searchKey:string, exact:boolean=false,ignoreVersion:boolean=true):Array<ResObject>
		{
			let s = this;			
			var temp=[];
			var ind:number;
			for (var key in GYLoader._resDataDict)
			{	
				let arr:string[];
				if(ignoreVersion)
				{
					arr = key.split("?");
					key = arr[0];
				}				
				ind = key.indexOf(searchKey);
				if(exact)
				{					
					if(key.substr(ind) == searchKey)
						temp.push(GYLoader._resDataDict[key]);
				}
				else if(ind == 0 || key.indexOf("/" + searchKey) > -1)
				{					
					temp.push(GYLoader._resDataDict[key]);
				}
			}
			return temp;
		}
		/**获取包含key键的资源,假设img文件夹下面的资源，如 img/,结尾带上/，以便区分文件夹节点 
		 * @param searchKey 资源键名
		 * @param exact 是否完全匹配 默认false
		*/
		public static getResByKey(searchKey:string, exact:boolean=false):Array<ResObject>
		{
			let s = this;			
			var temp=[];
			var ind:number;
			for (var key in GYLoader._resDict)
			{				
				ind = key.indexOf(searchKey);
				if(exact)
				{
					if(key.substr(ind) == searchKey)
						temp.push(GYLoader._resDataDict[key]);
				}
				else if(ind == 0 || key.indexOf("/" + searchKey) > -1)
				{					
					temp.push(GYLoader._resDict[key]);
				}
			}
			return temp;
		}	
		/**销毁资源，回收resObject并且解除资源字典对resObject的引用
		 * @param resObj ResObject资源
		 * @param dictType 资源类型 默认3 媒体资源和数据 1媒体资源 2数据		 
		*/
		public static deleteRes(resObj:ResObject,dictType:number=3):void
		{
			resObj.clear();
			if(dictType & 1)
				delete GYLoader._resDict[resObj.pathKey];
			if(dictType & 2)
				delete GYLoader._resDataDict[resObj.pathKey];
		}	
		/**删除包含key键的资源,删除img文件夹下面的资源，如 img/,结尾带上/，以便区分文件夹节点, deleteKey为空则删除全部资源 
		 * @param deleteKey 资源键名
		 * @param dictType 资源类型 默认3 媒体资源和数据 1媒体资源 2数据
		 * @param fuzzy 是否模糊匹配，默认true
		*/
		public static deleteResByKey(deleteKey:string,dictType:number=3, fuzzy:boolean=true):void
		{			
			// let temp:string[];
			let ind:number;
			let resObj:ResObject;			
			let len:number;
			if(dictType & 1)
			{
				if(fuzzy)
				{
					// temp=[];
					for (var key in GYLoader._resDict)
					{		
						resObj = GYLoader._resDict[key];
						if(deleteKey == null)
						{
							resObj.dispose();
							// temp.push(key);
						}
						else if(ind == 0 || key.indexOf("/" + deleteKey) > -1)
						{							
							resObj.dispose();						
							// temp.push(key);					
						}										
					}	
					// len = temp.length;
					// while(--len>-1)
					// 	delete GYLoader._resDict[temp[len]];
					// temp.length = 0;					
				}
				else
				{					
					GYLoader._resDict[deleteKey].dispose();
					// GYLoader._resDict[deleteKey].clear();
					// delete GYLoader._resDict[deleteKey];
				}									
			}			
			if(dictType & 2)
			{
				if(fuzzy)
				{
					// temp=[];
					for (var key in GYLoader._resDataDict)
					{
						resObj = GYLoader._resDataDict[key];
						if(deleteKey == null)
						{
							resObj.dispose();
							// temp.push(key);
						}
						else if(ind == 0 || key.indexOf("/" + deleteKey) > -1)
						{							
							resObj.dispose();
							// temp.push(key);							
						}
					}
					// len = temp.length;
					// while(--len>-1)
					// 	delete GYLoader._resDataDict[temp[len]];
					// temp.length = 0;
				}
				else
				{					
					GYLoader._resDataDict[deleteKey].dispose();
					// GYLoader._resDataDict[deleteKey].clear();								
					// delete GYLoader._resDataDict[deleteKey];
				}
			}			
		}
		/**获取位图、动画资源
		 * @param key 资源路径，需要后缀
		 * @param aliasKey 图集资源路径，如果存在图集，则key为图集内小图名称，需要后缀
		*/
		public static getRes(key:string,aliasKey:string=null)
		{
			let res:ResObject;			
			let newKey:string;		
			if(aliasKey == null)
                res = GYLoader._resDict[key];
            else
            {                
                newKey = aliasKey + "$" + key;
				res = GYLoader._resDict[newKey];                  
                let aliasRes:GYLite.ResObject;
                if(res == null)
                {                    
					aliasRes = GYLoader._resDict[aliasKey];
					if(aliasRes && aliasRes.param.jsonRes == null)
					{
						if(GYLoader._resDict[newKey] == null)//不存在，初始化一下
						{
							res = GYLite.GYLoader.getDataRes(aliasKey.replace(".png",".json"));
							if(res)																
								AtlasRender.getInstance().inputSpriteSheet(res,aliasRes.param.atlasId);
						}						
						res = GYLoader._resDict[newKey];
					}
                }				
            }			
			return res;
		}		
		/**获取二进制数据资源*/
		public static getDataRes(val:string)
		{
			return GYLoader._resDataDict[val];
		}
		public static setRes(key:string,val:ResObject):void
		{
			key = key.split("?")[0];
			let obj:ResObject = GYLoader._resDict[key];
			if(obj == val)
				return;
			if(obj!=null)
				obj.dispose();
			GYLoader._resDict[key] = val;
		}
		public static setDataRes(key:string,val:ResObject):void
		{
			key = key.split("?")[0];
			let obj:ResObject = GYLoader._resDataDict[key];
			if(obj == val)
				return;
			if(obj!=null)
				obj.dispose();
			GYLoader._resDataDict[key] = val;
		}
		/**获取媒体资源数组*/
		public static resArray():ResObject[]
		{
			let arr:ResObject[] = [];
			for(var key in GYLoader._resDict)
			{
				arr.push(GYLoader._resDict[key]);
			}
			return arr;
		}
		/**获取数据资源数组*/
		public static dataResArray():ResObject[]
		{
			let arr:ResObject[] = [];
			for(var key in GYLoader._resDataDict)
			{
				arr.push(GYLoader._resDataDict[key]);
			}
			return arr;
		}
		/**是否资源组(如图集、spine这类带多个资源一组的类型)*/
		public static isAssets(type:LoadType):boolean
		{
			return type == LoadType.TYPE_ATLAS || type == LoadType.TYPE_SPINE;
		}
		/**销毁加载系统*/
		public static dispose():void
		{
			GYLoader._disposed = true;
			let resObj:ResObject;
			let dict:any = GYLite.GYLoader._resDict;
			for (var key in dict) {                              
				resObj = dict[key];
				resObj.clear();
            }
			dict = GYLite.GYLoader._resDataDict;
			for (var key in dict) {                              
				resObj = dict[key];
				resObj.clear();
            }
			GYLite.GYLoader._resDict = null;
			GYLite.GYLoader._resDataDict = null;
		}
		/**加载系统是否已销毁*/
		public static get disposed():boolean
		{
			return GYLoader._disposed;
		}
		public static _disposed:boolean;
	}
}